home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Medal Software 2
/
Gold Medal Software Volume 2 (Gold Medal) (1994).iso
/
prog
/
asm_0_m.arj
/
CHGCOLOR.ASM
< prev
next >
Wrap
Assembly Source File
|
1988-04-12
|
25KB
|
500 lines
Title ChgColor
page 60,132
;------------------------------------------------------------------------
; ChgColor - Changes the palette colors reisters on an EGA video board.
; If no command line parameters are entered the registers are
; reset to theie factory defaults.
; Parameters should be in the following format:
;
; reg:value
;
; reg - is the register number (0 - 15)
; value - The decimal value (color) for that register
;
; The semi-colon is required to seperate the register number
; from the value. (Actually any white space will do.) Each entry
; on the command line must be seperated by a space.
;
; example:
;
; chgcolor 2:45 4 15 7:196
;------------------------------------------------------------------------
CR equ 13 ;carriage return
EOS equ 0 ;End of String
MAX_REG equ 15 ;max valid register
MAX_COLOR equ 255 ;max valid color
code segment para public 'code'
assume cs:code, ds:code, es:code, ss:code
org 100h
start:
jmp chgcolor ;skip data area
prog_name db 10,13,'ChgColor - EGA color palette changer v 1.0'
db 10,13,'$'
prog_length db $-prog_name ;length of program signiture
author db 'by John Toledo$'
;user changable registers/colors
user_colors db 0 ;black
db 1 ;Blue
db 2 ;Green
db 3 ;Cyan
db 4 ;Red
db 5 ;Magenta
db 20 ;Brown
db 7 ;Light Gray
db 56 ;Dark Gray
db 57 ;Light Blue
db 58 ;Light Green
db 59 ;Light Cyan
db 60 ;Light Red
db 61 ;Light Magenta
db 62 ;Yellow
db 63 ;White
defaults db 0 ;Black
db 1 ;Blue
db 2 ;Green
db 3 ;Cyan
db 4 ;Red
db 5 ;Magenta
db 20 ;Brown
db 7 ;Light Gray
db 56 ;Dark Gray
db 57 ;Light Blue
db 58 ;Light Green
db 59 ;Light Cyan
db 60 ;Light Red
db 61 ;Light Magenta
db 62 ;Yellow
db 63 ;White
old_int10 dd ?
;------------------------------------------------------------------------
; new_int10 - intercepts calls to INT 10h BIOS calls. If the request is
; going to attempt to change the EGA palette registers this routine will
; simply return. This leave the user selected colors in place.
;------------------------------------------------------------------------
hold_ah db ?
new_int10 proc far
mov cs:hold_ah,ah ;save the requested action type
pushf ;push flags to immulate INT call
call cs:old_int10 ;and do the call first thing
cmp cs:hold_ah,10h ;was the request a palette register
je reset_registers ;change ? If so, change 'em back
cmp cs:hold_ah,0bh
je reset_registers
cmp cs:hold_ah,0h
je reset_registers
jmp new_int10_exit ;no changes, just leave
reset_registers:
push si
push ds
push es
push cs ;set segment registers
pop ds ; to current segment
push cs
pop es
lea si,user_colors ;point to user selected colors
call set_registers ;and reset palette register
pop es
pop ds
pop si
new_int10_exit:
iret
new_int10 endp
;------------------------------------------------------------------------
; set_registers - set the EGA pallette registers to their factory
; defaults. These defaults may be found in the table DEFAULTS.
;------------------------------------------------------------------------
set_registers proc near
push bx
mov bx,0
default_loop:
mov ah,byte ptr [si+bx] ;move color to AH register
call SetPaletteReg ;set the pallette register
inc bx ;bump up to next register number
cmp bx,MAX_REG ;done all 16 (base 0)
jl default_loop ;nope, gon on
pop bx
ret ;all done, lets go back
set_registers endp
;------------------------------------------------------------------------
; SetPaletteReg - Sets an EGA color pallete register to the color
; specified.
;
; BL - register number
; AH - color
;------------------------------------------------------------------------
SetPaletteReg proc near
push ax ;save registers
push bx
push cx
push dx
push es
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; The following commented code is here in case the need arises to do
; the register change throught a BIOS call instead of the more hardware
; dependent port reads and writes.
;
; ;BL should have register number
; mov bh,ah ;move color to BH
; mov ax,1000h ;request set palette register
; int 10h ;call BIOS
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
mov ch,ah ;save reg color
mov ax,40h ;load BIOS data segment address
mov es,ax ;into ES
mov dx,es:[63h] ;DX = CRTC address reg (3x4h)
add dl,6 ;DX = Status reg (3xah)
push dx ;preserve this value
cli ;clear interrupts
in al,dx ;reset Attribute Controller address
;flip-flop
mov dl,0c0h ;DX = 3c0h
mov al,bl ;AL = PaletteRegNumber
out dx,al ;update one palette register
mov al,ch ;AL = PaletteRegColor
out dx,al ;set it
pop dx ;DX = status register port
in al,dx
mov dl,0c0h
mov al,20h ;set bit 5 of
out dx,al ; Attribute controller address reg
sti ;restart interrupts
pop es ;restore registers
pop dx
pop cx
pop bx
pop ax
ret
SetPaletteReg endp
stay_res_mark label byte ;keep stuff above resident
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Non-memory resident code below.
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;------------------------------------------------------------------------
; The following data was placed down here so it wouldn't remain resident.
;------------------------------------------------------------------------
bad_reg_msg db 10,13,'ERROR - invalid register number.',10,13,'$'
bad_color_msg db 10,13,'ERROR - invalid color number.',10,13,'$'
no_color_msg db 10,13,'ERROR - register not followed by color.'
db 10,13,'$'
defaults_msg db 10,13,'Factory default colors restored.$'
user_msg db 10,13,'New colors set.$'
parm db 80 dup(0) ;temporary string area
hold_reg dw ? ;temporary register area
;------------------------------------------------------------------------
; chgcolor - main routine for changing EGA color palette registers. It
; will reset the factory default colors if there are no command line
; parameters or set the user specified colors, if there are any, on the
; command line.
;------------------------------------------------------------------------
chgcolor proc near
lea dx,prog_name ;set up to display program name
mov ah,9 ;request DOS display string
int 21h ;call DOS
mov si,80h ;point to parm count in PSP
cmp byte ptr [si],0h ;anything there ?
je reset_colors ;no, reset factory defaults
inc si ;make sure its not a blank line
call skip_delims ;skip any white space out there
cmp byte ptr[si],CR ;anything there ?
je reset_colors ;no, reset factory defaults
call set_up_colors ;yes, set new user colors
jc err_exit ;exit if we had an error
lea si,user_colors ;load addres of user EGA colors
lea dx,user_msg ;show colors changed message
jmp leave ;and exit
reset_colors:
lea si,defaults ;load addres of default EGA colors
lea di,user_colors ;and copy it to the user table
mov cx,8 ;length of table in words
cld ;move from left to right
rep movsw ;and do it
lea si,defaults ;load addres of default EGA colors
lea dx,defaults_msg ;show defaults set message
leave:
mov ah,9 ;request DOS display string
int 21h ;and display color changes message
call set_registers ;reset factory defaults
assume es:nothing
mov ax,3510h ;request get video vector address
int 21h ;call DOS to do it
mov word ptr [old_int10],bx ;save the offset
mov word ptr [old_int10+2],ES ;save the segment
lea si,prog_name ;get offset of program
mov di,si ;signiture for comparison
xor ch,ch ;zero out CH
mov cl,prog_length ;amount to compare
rep cmpsb ;do the compare
jcxz installed ;already instaled ?
;no, lets install
mov dx, offset new_int10 ;offset of new INT 10h
mov ax,2510h ;request DOS set vector
int 21h ;call DOS to do it
lea dx,stay_res_mark ;load address of end of program
int 27h ;old DOS terminate stay resident
installed:
lea si,user_colors ;load addres of user colors
mov di,si ;to copy to mem res copy of program
cld ;copy from left to right
mov cx,8 ;amount in words to copy
rep movsw ;do the move
err_exit:
int 20h ;old DOS terminate program
chgcolor endp
;------------------------------------------------------------------------
; set_up_colors - sets the user requested colors. It goes throught the
; command line list of registers and colors recursively calling the
; line parser until all of the command line has been processed.
; DI should be pointing to the beginning of the command line parameters.
;------------------------------------------------------------------------
set_up_colors proc near
lea di,user_colors ;set address of user table
xor bx,bx ;set changed counter to zero
call get_reg ;get reg number (returned in AX)
cmp byte ptr [si],CR ;end of the command line ?
je no_color_err ;yep, get out of here
cmp ax,MAX_REG ;invalid register ?
jle good_reg ;nope, keep going
lea dx,bad_reg_msg ;set up to display register error
call display_err ;display error messages
jmp set_colors_exit ;lets leave now
good_reg:
mov hold_reg,ax ;save the register number
call get_color ;get the color we need to set (AX)
cmp ax,MAX_COLOR ;invalid color (not 0 - 255)
jle good_color ;nope, keep going
lea dx,bad_color_msg ;set up to display bad color error
call display_err ;display error messages
jmp set_colors_exit ;lets leave now
good_color:
mov bx,hold_reg ;move register number to BX
mov byte ptr [di+bx],al ;move color to user table
cmp byte ptr [si],CR ;end of the command line ?
je set_colors_exit ;yep, get out of here
jmp set_up_colors ;no, get next guy to set
no_color_err:
lea dx,no_color_msg ;set up to display error
call display_err ;and do it
clc ;set carry to indicate error
ret
set_colors_exit:
ret
set_up_colors endp
;------------------------------------------------------------------------
; get_color - converts the string pointed to by DI into a binary number
; and places the number in AX. It searches for a space, tab or carriage
; return which should follow a color number.
;------------------------------------------------------------------------
get_color proc near
push cx
push di
call get_field ;get the color number string
lea di,parm ;point to start of color string
cmp byte ptr [di],EOS ;was it the end of the line ?
je get_color_exit ;yep, get out
push si ;save position in string
lea si,parm ;reset SI to beginning of number
call atoi ;convert it to binary (in AX)
pop si ;restore position in string
get_color_exit:
pop di
pop cx
ret
get_color endp
;------------------------------------------------------------------------
; get_reg - converts the string pointed to by DI into a binary number
; and places the number in AX. It searches for the ':' (colon) which
; should follow a register and places a 0 (end of string) in its place.
;------------------------------------------------------------------------
get_reg proc near
push cx
push di
call get_field ;get the register number string
cmp byte ptr [si],CR ;was it the end of the line ?
je get_reg_exit ;yep, get out
push si ;save position in string
lea si,parm ;reset SI to beginning of number
call atoi ;convert it to binary (in AX)
pop si ;restore position in string
get_reg_exit:
pop di
pop cx
ret
get_reg endp
;------------------------------------------------------------------------
; get_field - gets the next parameter from a string pointed to by SI.
; Leaves SI pointing to the next position in the string and copies the
; parameter in the to the string parm. Returns ax = 0ffffh if the parm
; is the last one in the string.
;------------------------------------------------------------------------
get_field proc near
push di
lea di,parm ;set up desination address
call skip_delims ;go past leading spaces, tabs and :
get_field_loop:
cmp byte ptr [si],CR ;at end of command line parms ?
je get_field_exit ;yep, get out of here
cmp byte ptr [si],' ' ;at end of command line parms ?
je get_field_exit ;yep, get out of here
cmp byte ptr [si],':' ;at end of command line parms ?
je get_field_exit ;yep, get out of here
mov ah,byte ptr [si] ;copy character
mov byte ptr [di],ah ; to parm string
inc di ;bump up string pointers
inc si
jmp get_field_loop ;and keep looking for more
get_field_exit:
mov byte ptr [di],EOS ;mark end of string
pop di
ret
get_field endp
;------------------------------------------------------------------------
; skip_delims - searches the string (area) pointed to by SI for the
; first non-white space. It skips over spaces, tabs and colon characters
; and returns with SI pointed to the first non-white space.
;------------------------------------------------------------------------
skip_delims proc near
push di ;save DI
mov cx,128 ;set CX to max string length
mov di,si ;copy SI to DI for scasb call
dec di ;adjust for looping
mov al,' ' ;search for space
cld ;set direction to go left to right
keep_looking:
inc di ;point to next character
repe scasb ;skip those blanks
dec di ;adjust DI to correct position
cmp byte ptr [di],9 ;is it a tab
je keep_looking ;yep, we're done
cmp byte ptr [di],':' ;is it a colon
je keep_looking ;yep, we're done
skip_delims_exit:
mov si,di ;set SI to first non-white space
pop di ;restore DI
ret
skip_delims endp
;------------------------------------------------------------------------
; display_err - displays the message pointed to by the DX register and
; then displays the current contents of the temporary string parm.
;------------------------------------------------------------------------
display_err proc near
mov ah,9 ;set up to display message
int 21h ;call DOS to display message
lea di,parm ;address of bad register string
display_loop:
cmp byte ptr [di],EOS ;end of the string ?
je display_exit ;yep, let get out of here
mov ah,2 ;request DOS display character
mov dl,byte ptr [di] ;move character to DL for DOS
int 21h ;display that sucker
inc di ;point to next character
jmp display_loop ;go get the next one
display_exit:
ret
display_err endp
;------------------------------------------------------------------------
; ATOI.ASM - convert ASCII string to
; 16-bit decimal integer.
;
; Copyright 1987 Ziff Communications Co.
; Ray Duncan
;
; Call with: DS:SI = address of string
;
; where 'string' is in the form
;
; [whitespace][sign][digits]
;
; Returns: AX = result
; DS:SI = address+1 of terminator
;
; other registers preserved
;
; Like the C library 'atoi', this routine gives no
; warning in the event of overflow, and terminates
; on the first invalid character.
;------------------------------------------------------------------------
blank equ 20h ; ASCII blank character
tab equ 09h ; ASCII tab character
atoi proc near ; ASCII to 16-bit integer
push bx ; save registers
push cx
push dx
xor bx,bx ; initialize forming answer
xor cx,cx ; initialize sign flag
atoi1:
lodsb ; scan off whitespace
cmp al,blank ; ignore leading blanks
je atoi1
cmp al,tab ; ignore leading tabs
je atoi1
cmp al,'+' ; if + sign proceed
je atoi2
cmp al,'-' ; is it - sign?
jne atoi3 ; no, test if numeric
dec cx ; was - sign, set flag
; for negative result
atoi2:
lodsb ; get next character
atoi3:
cmp al,'0' ; is character valid?
jb atoi4 ; jump if not '0' to '9'
cmp al,'9'
ja atoi4 ; jump if not '0' to '9'
and ax,0fh ; isolate lower four bits
xchg bx,ax ; multiply answer x 10
mov dx,10
mul dx
add bx,ax ; add this digit
jmp atoi2 ; convert next digit
atoi4:
mov ax,bx ; result into AX
jcxz atoi5 ; jump if sign flag clear
neg ax ; make result negative
atoi5:
pop dx ; restore registers
pop cx
pop bx
ret ; back to caller
atoi endp
code ends
end start